%% 3. Endpoint Detection Code

clear; clc;

%% Load Skeletonized Vessel Image
[skeletonFile, skeletonPath] = uigetfile('*', 'Select skeletonized vessel image'); 
if isequal(skeletonFile, 0)
    disp('Selection cancelled.'); return;
else
    vesselSkeleton = imread(fullfile(skeletonPath, skeletonFile));
    if size(vesselSkeleton, 3) == 3
        vesselSkeleton = rgb2gray(vesselSkeleton);
    end
    vesselSkeleton = imbinarize(vesselSkeleton);
    figure, imshow(vesselSkeleton), title('Skeletonized Vessel');
end

%% Detect Endpoints
endpoints = bwmorph(vesselSkeleton, 'endpoints');
[endY, endX] = find(endpoints);
endCoordinates = [endX, endY];

%% Load Optic Disc Coordinates
load('OD_coordinates.mat', 'odData');
odX = odData.CenterX; odY = odData.CenterY; odRadius = odData.Radius;

%% Identify Vessel Pixels Inside OD
[whiteY, whiteX] = find(vesselSkeleton);
whiteCoords = [whiteX, whiteY];
distToOD = sqrt((whiteCoords(:, 1) - odX).^2 + (whiteCoords(:, 2) - odY).^2);
insideOD = distToOD <= odRadius;
insideCoords = whiteCoords(insideOD, :);

% Create binary mask to exclude OD region
maskOutsideOD = true(size(vesselSkeleton));
maskOutsideOD(sub2ind(size(vesselSkeleton), insideCoords(:,2), insideCoords(:,1))) = false;

%% Filter Endpoints Outside OD
distEndToOD = sqrt((endCoordinates(:,1) - odX).^2 + (endCoordinates(:,2) - odY).^2);
outsideEndpoints = endCoordinates(distEndToOD > odRadius, :);

%% Define Start Points (sample)
startPoints = [
    260,224; 227,228; 201,265; 201,277;
    219,309; 252,319; 281,307; 290,245
];

%% Trace Connections from Endpoints to Start Points (BFS)
connectedEndpoints = []; connectedStartPoints = [];

for i = 1:size(outsideEndpoints, 1)
    current = outsideEndpoints(i, :);
    visited = false(size(vesselSkeleton));
    queue = current;

    while ~isempty(queue)
        pixel = queue(1,:); queue(1,:) = [];

        if any(ismember(startPoints, pixel, 'rows'))
            connectedEndpoints = [connectedEndpoints; current]; %#ok<AGROW>
            connectedStartPoints = [connectedStartPoints; pixel]; %#ok<AGROW>
            break;
        end

        % 8-connected neighbors
        neighbors = [
            pixel(2)-1, pixel(1)-1; pixel(2)-1, pixel(1); pixel(2)-1, pixel(1)+1;
            pixel(2),   pixel(1)-1;                    pixel(2),   pixel(1)+1;
            pixel(2)+1, pixel(1)-1; pixel(2)+1, pixel(1); pixel(2)+1, pixel(1)+1
        ];

        for j = 1:size(neighbors,1)
            ny = neighbors(j,1); nx = neighbors(j,2);
            if ny > 0 && ny <= size(vesselSkeleton,1) && nx > 0 && nx <= size(vesselSkeleton,2)
                if vesselSkeleton(ny, nx) && ~visited(ny, nx) && maskOutsideOD(ny, nx)
                    visited(ny, nx) = true;
                    queue = [queue; nx, ny]; %#ok<AGROW>
                end
            end
        end
    end
end

%% Visualization
figure, imshow(vesselSkeleton), title('Connections to OD'); hold on;
plot(insideCoords(:,1), insideCoords(:,2), 'g.', 'MarkerSize', 5);
for i = 1:size(connectedEndpoints,1)
    plot([connectedEndpoints(i,1), connectedStartPoints(i,1)], [connectedEndpoints(i,2), connectedStartPoints(i,2)], 'r-');
    plot(connectedEndpoints(i,1), connectedEndpoints(i,2), 'bo');
    plot(connectedStartPoints(i,1), connectedStartPoints(i,2), 'go');
end
hold off;

%% Export to Excel
dataOut = cell(size(connectedEndpoints,1), 2);
for i = 1:size(connectedEndpoints,1)
    dataOut{i,1} = sprintf('(%d, %d)', connectedStartPoints(i,1), connectedStartPoints(i,2));
    dataOut{i,2} = sprintf('(%d, %d)', connectedEndpoints(i,1), connectedEndpoints(i,2));
end
xlswrite('Tortuosity_StartEndPoints.xlsx', {'Startpoint (x, y)', 'Endpoint (x, y)'}, 'Sheet1', 'A1');
xlswrite('Tortuosity_StartEndPoints.xlsx', dataOut, 'Sheet1', 'A2');
